package org.learn.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类，包括jwt的创建、验证等方法
 */
public class JwtUtil {
    private static final String SECRET = "org.learnjwt.secret";  //秘钥
    private static final String ISSUER = "jwtlearn";
    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);


    public static void main(String[] ss) throws Exception {
        /*String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNTY2NjA3OTk2LCJ1c2VybmFtZSI6ImFkbWluIn0.DgsjV12ke8aFkIWzHKOkxGfGPEQTevnqN3tY3-w19_E";
        String verifyToken = verifyToken(token);
        System.out.println(verifyToken);
        SysUser sysUser = JSON.parseObject(verifyToken, SysUser.class);
        System.out.println(sysUser.getRoles().get(0).getRoleName());*/
        //String token = createToken("1", 6);

        String token = createToken("user info", "admin");
        System.out.println(token);
        // String token = createToken("1", "admin");  //创建token
        //  System.out.println(token);
        /*String gToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJhZG1pblwiOnRydWUsXCJhdmF0YXJcIjpcImdyb3VwMS9NMDAvMDEvRDQvd0tnQnNseFN5MnFBSVRQcUFBQ3BHNklxbm9BNjEyXzIwMHgyMDAucG5nXCIsXCJjcmVhdGVUaW1lXCI6MTUyMTE3MTE4MDAwMCxcImRlbEZsYWdcIjpcIjBcIixcImRlcHRcIjp7XCJkZXB0SWRcIjoxMDMsXCJkZXB0TmFtZVwiOlwi6IKh5Lu95q-N5YWs5Y-4XCIsXCJvcmRlck51bVwiOlwiMVwiLFwicGFyYW1zXCI6e30sXCJwYXJlbnRJZFwiOjEwMSxcInN0YXR1c1wiOlwiMFwifSxcImRlcHRJZFwiOjEwMyxcImVtYWlsXCI6XCJyeUAxNjMuY29tXCIsXCJsb2dpbkRhdGVcIjoxNTY2Nzk3ODEwNDU5LFwibG9naW5JcFwiOlwiMTI3LjAuMC4xXCIsXCJsb2dpbk5hbWVcIjpcImFkbWluXCIsXCJwYXJhbXNcIjp7fSxcInBob25lbnVtYmVyXCI6XCIxNTg4ODg4ODg4OFwiLFwicG9zdHNcIjpbe1wiZmxhZ1wiOmZhbHNlLFwicGFyYW1zXCI6e30sXCJwb3N0Q29kZVwiOlwiY2VvXCIsXCJwb3N0SWRcIjoxLFwicG9zdE5hbWVcIjpcIuiRo-S6i-mVv1wifV0sXCJyZW1hcmtcIjpcIueuoeeQhuWRmFwiLFwicm9sZXNcIjpbe1wiY3JlYXRlVGltZVwiOjE1MjExNzExODAwMDAsXCJkYXRhU2NvcGVcIjpcIjFcIixcImRlbEZsYWdcIjpcIjBcIixcImZsYWdcIjpmYWxzZSxcInBhcmFtc1wiOnt9LFwicmVtYXJrXCI6XCLnrqHnkIblkZhcIixcInJvbGVJZFwiOjEsXCJyb2xlS2V5XCI6XCJhZG1pblwiLFwicm9sZU5hbWVcIjpcIueuoeeQhuWRmFwiLFwicm9sZVNvcnRcIjpcIjFcIixcInN0YXR1c1wiOlwiMFwifV0sXCJzYWx0XCI6XCIxMTExMTFcIixcInNleFwiOlwiMVwiLFwic3RhdHVzXCI6XCIwXCIsXCJ1c2VySWRcIjoxLFwidXNlck5hbWVcIjpcIueuoeeQhuWRmFwifSIsImlzcyI6InJ1b3lpIiwiZXhwIjoxNTY2Nzk3ODExLCJ1c2VybmFtZSI6ImFkbWluIn0.XIl_y9Vp9NA5jyfZOWDHXfs2cw3WZrihhc2IqY4wyfQ";
        Date issuedAt = getIssuedAt(gToken);  //到期时间
        System.out.println(issuedAt);
        //剩余时间
        long liveTime = getLiveTime(gToken);  //剩余时间
        System.out.println(liveTime);

        //获取用户名
        String userName = getUsername(gToken);
        System.out.println(userName);
*/
        //验证Token
        // boolean to = verify(gToken,"admin");
        //System.out.println(to);
    }

    /**
     * 生成token
     *
     * @param username 用户名
     * @return 返回生成的token字符串
     */
    public static String createToken(String infoJson, String username) throws Exception {
        int second = 100000;  //jwt token有效期  毫秒
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        // 附带username信息
        return JWT.create()
                .withIssuer(ISSUER)  //jwt签发者
                .withClaim("username", username)  //用户名
                .withExpiresAt(DateUtils.addSeconds(new Date(), second))  //有效日期
                .withSubject(infoJson)  //用户信息
                .sign(algorithm);//签名算法


    }

    /**
     * 校验token是否正确
     *
     * @param token TOKEN
     * @return boolean
     */
    public static Map verify(String token, String username) {
        Map result = new HashMap<String, Object>(2);
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            String subject = jwt.getSubject();
            result.put("username", username);
            result.put("isSuccess", true);
            result.put("ex", null);
            result.put("subject", subject);
            return result;
        } catch (Exception e) {
            logger.info("鉴权失败", e);
            result.put("isSuccess", false);
            result.put("exception", e);

        }
        return result;

    }


    /**
     * 获得token的到期时间
     *
     * @return token中包含的签发时间
     */
    public static Date getIssuedAt(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSUER).build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getExpiresAt();
        } catch (Exception e) {
            logger.error("获取有效时间失败", e);
            return null;
        }
    }

    /**
     * 获得token的到期剩余时间 毫秒
     *
     * @return token中包含的签发时间
     */
    public static long getLiveTime(String token) {
        try {
            Date date = getIssuedAt(token);
            if (date != null) {
                return (date.getTime() - new Date().getTime());
            }
        } catch (Exception e) {
            logger.error("获取剩余有效时间失败", e);
            return 0;
        }
        return 0;
    }


    /**
     * token是否过期
     *
     * @return true：过期
     */
    public static boolean isTokenExpired(String token) {
        Date now = Calendar.getInstance().getTime();
        Date issuedAt = getIssuedAt(token);
        return issuedAt == null ? true : issuedAt.before(now);
    }

    /**
     * 生成随机盐,长度32位
     *
     * @return
     */
/*
    public static String generateSalt() {
        SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
        String hex = secureRandom.nextBytes(16).toHex();
        return hex;
    }
*/


    /**
     * 无需解密直接获得token中的用户名
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            e.printStackTrace();
            return null;
        }
    }


}
